Skip to content

Lpcox/initial implementation#2

Merged
lpcox merged 8 commits into
mainfrom
lpcox/initial-implementation
Dec 20, 2025
Merged

Lpcox/initial implementation#2
lpcox merged 8 commits into
mainfrom
lpcox/initial-implementation

Conversation

@lpcox

@lpcox lpcox commented Dec 20, 2025

Copy link
Copy Markdown
Collaborator

Initial implementation of mcp gateway.

@lpcox lpcox merged commit efa692c into main Dec 20, 2025
lpcox added a commit that referenced this pull request Jan 8, 2026
Copilot AI added a commit that referenced this pull request Jan 20, 2026
- Add generic trySDKTransport function to handle common connection logic
- Refactor tryStreamableHTTPTransport to use trySDKTransport
- Refactor trySSETransport to use trySDKTransport
- Reduces code duplication by ~40 lines (Pattern #2 from issue #353)

Co-authored-by: lpcox <15877973+lpcox@users.noreply.github.com>
lpcox added a commit that referenced this pull request May 6, 2026
…5192)

# Test Coverage Improvement: `server.GetServerStatus` /
`server.GetServerIDs`

## Function Analyzed

- **Package**: `internal/server`
- **Function**: `GetServerStatus` (and `GetServerIDs`)
- **File**: `internal/server/unified.go`
- **Previous Coverage**: Partial — the `!state.StartedAt.IsZero()`
branch (running server uptime calculation) was never exercised
- **Complexity**: Medium — iterates server pool, reads concurrent state,
conditional uptime computation

## Why This Function?

`GetServerStatus` has two execution paths:
1. `state.StartedAt.IsZero()` → uptime = 0 (error/not-started state)
2. `!state.StartedAt.IsZero()` → `uptime =
int(time.Since(state.StartedAt).Seconds())` (running state)

The existing test `TestGetServerStatus_ErrorOnFailedLaunch` in
`health_test.go` only covers path #1. Path #2 — where a server
successfully launches and `StartedAt` is set — had zero test coverage.
This branch is core to the health-reporting surface used by agents to
understand server state.

## Tests Added

- ✅ **Empty config** — `GetServerStatus` returns an empty map when no
servers are configured
- ✅ **Running HTTP backend** — covers the `!StartedAt.IsZero()` uptime
branch; asserts `status == "running"` and `uptime >= 0`
- ✅ **Errored server** — stdio server that fails launch reports `status
== "error"` and `uptime == 0`
- ✅ **Mixed-state multiple servers** — one running + one errored,
checked independently
- ✅ **Nil config** — `GetServerStatus` handles nil config without panic
- ✅ **`GetServerIDs` matches config keys** — asserts exact set of server
IDs returned
- ✅ **`GetServerStatus` keys equal `GetServerIDs`** — consistency
invariant between the two methods

## Coverage Report

```
Before: 0% for the running-server uptime branch in GetServerStatus
After:  branch covered via TestGetServerStatus_RunningServer
```

## Implementation Notes

Tests use `httptest.Server` (no Docker required) as a minimal HTTP MCP
backend. The `mockMCPServer` helper in this file responds to
`initialize`, `notifications/initialized`, and `tools/list` JSON-RPC
calls — following the same pattern established in
`unified_http_backend_test.go`. The `decodeJSONRPCMethod` helper is
reused from that file (same package).

---
*Generated by Test Coverage Improver*
*Next run will target the next most complex under-tested function*




> [!WARNING]
> **⚠️ Firewall blocked 1 domain**
>
> The following domain was blocked by the firewall during workflow
execution:
>
> - `proxy.golang.org`
>
> To allow these domains, add them to the `network.allowed` list in your
workflow frontmatter:
>
> ```yaml
> network:
>   allowed:
>     - defaults
>     - "proxy.golang.org"
> ```
>
> See [Network
Configuration](https://github.github.com/gh-aw/reference/network/) for
more information.


> Generated by [Test Coverage
Improver](https://github.com/github/gh-aw-mcpg/actions/runs/25434463369/agentic_workflow)
· ● 18.9M ·
[◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw-mcpg+%22gh-aw-workflow-id%3A+test-coverage-improver%22&type=pullrequests)

<!-- gh-aw-agentic-workflow: Test Coverage Improver, engine: copilot,
version: 1.0.21, model: auto, id: 25434463369, workflow_id:
test-coverage-improver, run:
https://github.com/github/gh-aw-mcpg/actions/runs/25434463369 -->

<!-- gh-aw-workflow-id: test-coverage-improver -->
lpcox added a commit that referenced this pull request Jun 9, 2026
…etOrLaunchForSession (#7268)

🤖 *This PR was created by [Repo
Assist](https://github.com/github/gh-aw-mcpg/actions/runs/27209796205),
an automated AI assistant.*

## Summary

When `GetOrLaunchForSession` handles an HTTP backend, it previously
called `getServerConfig` once (acquiring the read lock), then
immediately delegated to `GetOrLaunch` which called `getServerConfig` a
second time — acquiring the same read lock twice per HTTP request.

## Root Cause

`GetOrLaunchForSession` needed to know the backend type before routing.
For HTTP backends it called `GetOrLaunch`, which blindly re-fetched the
config:

```go
// Before: two lock acquisitions for HTTP
func GetOrLaunchForSession(...) {
    serverCfg, _ := l.getServerConfig(serverID) // lock #1
    if serverCfg.Type == "http" {
        return GetOrLaunch(l, serverID)          // lock #2 inside
    }
}
```

## Fix

Extract the inner logic of `GetOrLaunch` into a private
`getOrLaunchWithConfig` helper that accepts a pre-fetched
`*config.ServerConfig`. Both public functions now call this helper after
their single config lookup:

```go
// After: one lock acquisition per request
func GetOrLaunchForSession(...) {
    serverCfg, _ := l.getServerConfig(serverID)  // lock #1 only
    if serverCfg.Type == "http" {
        return getOrLaunchWithConfig(l, serverID, serverCfg) // no extra lock
    }
}
```

## Trade-offs

- **No public API changes** — `GetOrLaunch` and `GetOrLaunchForSession`
signatures are unchanged.
- **No behaviour change** — The new `getOrLaunchWithConfig` is a
verbatim extraction of the existing `syncutil.GetOrCreate` call body.
- **Minor lock contention reduction** — For HTTP backends routed through
`GetOrLaunchForSession`, the `getServerConfig` RLock is acquired once
instead of twice.

Addresses: #7254

## Test Status

⚠️ **Infrastructure failure**: `go build` and `go test` require
downloading modules from `proxy.golang.org`, which is blocked by the
network firewall in this environment. The code change is a
straightforward extraction with no behavioural changes — the
`getOrLaunchWithConfig` body is an exact verbatim copy of the original
`syncutil.GetOrCreate` closure in `GetOrLaunch`. All existing tests for
`GetOrLaunchForSession_HTTPBackend`, `GetOrLaunch_*`, and related
launchers remain valid and unchanged.

- ✅ `gofmt` — no formatting changes
- ⚠️ `go build` — blocked (proxy.golang.org unreachable in CI sandbox)
- ⚠️ `go test` — blocked (same reason)




> [!WARNING]
> <details>
> <summary>Firewall blocked 1 domain</summary>
>
> The following domain was blocked by the firewall during workflow
execution:
>
> - `proxy.golang.org`
>> To allow these domains, add them to the `network.allowed` list in
your workflow frontmatter:
>
> ```yaml
> network:
>   allowed:
>     - defaults
>     - "proxy.golang.org"
> ```
>
> See [Network
Configuration](https://github.github.com/gh-aw/reference/network/) for
more information.
>
> </details>


> Generated by [Repo
Assist](https://github.com/github/gh-aw-mcpg/actions/runs/27209796205) ·
sonnet46 5.2M ·
[◷](https://github.com/search?q=repo%3Agithub%2Fgh-aw-mcpg+%22gh-aw-workflow-id%3A+repo-assist%22&type=pullrequests)
>
<details>
<summary>Add this agentic workflows to your repo</summary>

To install this agentic workflow, run

```
gh aw add githubnext/agentics@851905c
```
</details>


<!-- gh-aw-agentic-workflow: Repo Assist, engine: copilot, version:
1.0.52, model: claude-sonnet-4.6, id: 27209796205, workflow_id:
repo-assist, run:
https://github.com/github/gh-aw-mcpg/actions/runs/27209796205 -->

<!-- gh-aw-workflow-id: repo-assist -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant